package erfgame.core.entity;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


import erfgame.core.DescribedValue;
import erfgame.core.world.World;
import erfgame.core.world.WorldAwarePrototype;
import erfgame.core.world.terrain.MaterialType;

@SuppressWarnings("serial")
public class Part extends AbstractEntity implements HasMaterialType, Entity, Attachable, Composite, WorldAwarePrototype<Part> {
	 private MaterialType materialType;
	 private Entity parent;
	 private List<CompositeAssociation> subParts;
	 private Map<String, DescribedValue<Object>> descriptions;
	 
	 public Part( long id, EntityType entityType, MaterialType materialType ) {
		 super( id, entityType );
		 this.materialType = materialType;
	 }
	 
	 public Part( 
			 long id, 
			 EntityType entityType, 
			 MaterialType materialType, 
			 List<CompositeAssociation> subParts 
	) {
		 super(id, entityType);
		 this.materialType = materialType;
		 this.subParts = subParts;
	 }

	 public Part( 
			 long id, 
			 EntityType entityType, 
			 MaterialType materialType, 
			 List<CompositeAssociation> subParts, 
			 Map<String, DescribedValue<Object>> descriptions
	) {
		 this( id, entityType, materialType, subParts );
		 this.descriptions = descriptions;
	 }

	 
	 public Map<String, DescribedValue<Object>> getDescriptions() {
		 return this.descriptions;
	 }
	 
	 public void setDescriptions( Map<String, DescribedValue<Object>> descriptions ) {
		 this.descriptions = descriptions;
	 }
	 
	 public MaterialType getMaterialType() {
		 return this.materialType;
	 }

	 public Entity getParent() {
		 return this.parent; 
	 }

	public void addPart(CompositeAssociationType type, Entity bodyPart)
			throws CompositeException {
		this.subParts.add( new CompositeAssociation( type, bodyPart ) );
	}

	public List<CompositeAssociation> getAssociations() {
		return this.subParts;
	}

	public void removePart(CompositeAssociationType type, Entity bodyPart)
			throws CompositeException {
		throw new CompositeException( "unsupported" );
	} 

	public Part spawn(World world) {
		long entityId = world.getNextEntityId();
		return new Part(
				entityId, 
				entityType,
				materialType,
				spawnSubParts( world ), 
				descriptions
		);
	}
	
	@SuppressWarnings("unchecked")
	protected List<CompositeAssociation> spawnSubParts( World world ) {
		if( this.subParts != null ) {
			ArrayList<CompositeAssociation> result = new ArrayList<CompositeAssociation>( this.subParts.size() );
			for( int i=0; i<this.subParts.size(); i++ ) {
				CompositeAssociation subPart = this.subParts.get( i );
				Entity entity = subPart.getEntity();
				if( entity instanceof WorldAwarePrototype ) {
					entity = ((WorldAwarePrototype<Entity>)entity).spawn(world);
					result.add( new CompositeAssociation( subPart.getType(), entity ) );
				}
			}
			return result;
		} else { 
			return null;
		}
	}
	 
}
